#ifndef MAPPERMMC3_H
#define MAPPERMMC3_H

#include "Mapper.h"
#include <array>

PNE_NAMESPACE_BEGIN

struct MapperMMC3 : public Mapper
{
    MapperMMC3(Cartridge &cart, std::function<void(void)> interrupt_callback, std::function<void(void)> mirroring_callback);

    Byte ReadPRG(Address addr);
    void WritePRG(Address addr, Byte value);

    NameTableMirroring GetNameTableMirroring();
    Byte ReadCHR(Address addr);
    void WriteCHR(Address addr, Byte value);

    void ScanLineIRQ() override;

private:
    // control variables
    uint32_t m_targetRegister;
    bool m_prgBankMode;
    bool m_chrInversion;

    uint32_t m_bankRegister[8];

    bool m_irqEnabled;
    Byte m_irqCounter;
    Byte m_irqLatch;
    bool m_irqReloadPending;

    std::vector<Byte> m_prgRam;
    std::vector<Byte> m_mirroringRam;

    const Byte *m_prgBank0;
    const Byte *m_prgBank1;
    const Byte *m_prgBank2;
    const Byte *m_prgBank3;

    std::array<uint32_t, 8> m_chrBanks; // cap : 8

    NameTableMirroring m_mirroring;
    std::function<void(void)> m_mirroringCallback;
    std::function<void()> m_interruptCallback;
};

PNE_NAMESPACE_END

#endif // MAPPERMMC3_H
       // DONE